<?php

namespace app\admin\controller;

use app\common\library\Utils;
use app\common\model\apply\Advance;
use app\common\model\apply\Payment;
use app\common\model\apply\Reimbursement;
use app\common\service\workflow\WFCreate;
use app\common\service\workflow\Workflow;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use think\Exception;
use think\facade\Cache;
use Throwable;
use app\common\controller\Backend;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;

/**
 * 项目
 */
class Project extends Backend
{
    /**
     * Project模型对象
     * @var object
     * @phpstan-var \app\common\model\Project
     */
    protected object $model;

    protected array|string $preExcludeFields = ['id', 'sub_total', 'total'];

    protected array $withJoinTable = ['manager'];

    protected string|array $quickSearchField = ['title', 'id'];

    protected array $noNeedPermission = ['index','Statics', 'wfrecord', 'export', 'toAudit'];

    public function initialize(): void
    {
        parent::initialize();
        $this->model = new \app\common\model\Project;
    }

    /**
     * 查看
     * @throws Throwable
     */
    public function index(): void
    {
        // 如果是 select 则转发到 select 方法，若未重写该方法，其实还是继续执行 index
        if ($this->request->param('select')) {
            $this->select();
        }

        /**
         * 1. withJoin 不可使用 alias 方法设置表别名，别名将自动使用关联模型名称（小写下划线命名规则）
         * 2. 以下的别名设置了主表别名，同时便于拼接查询参数等
         * 3. paginate 数据集可使用链式操作 each(function($item, $key) {}) 遍历处理
         */
        list($where, $alias, $limit, $order) = $this->queryBuilder();
        if ($this->request->param('select')) {
            $where['state'] = 1;
        }
        if($this->request->post('project_id')){
            $where[$alias['ba_project'].'.id'] = $this->request->post('project_id');
        }
        $auth_group_arr = $this->auth->group_arr;
        $is_allow_all = count(array_intersect(['1', '2', '3', '10'],$auth_group_arr));
        $admin_id = $this->auth->id;
        $res = $this->model
            ->withJoin($this->withJoinTable, $this->withJoinType)
            ->alias($alias)
            ->where($where)
            ->whereRaw($is_allow_all.' > 0 or manager_id = "'.$admin_id.'" or creater_id = "'.$admin_id.'" ')
            ->order($order)
            ->paginate($limit);
        $res->visible(['manager' => ['nickname']]);

        $this->success('', [
            'list'   => $res->items(),
            'total'  => $res->total(),
            'remark' => get_route_remark(),
        ]);
    }

    public function select(): void{
        list($where, $alias, $limit, $order) = $this->queryBuilder();
        $where['state'] = 1;
        $where['budget_audit_state'] = 3;
        $auth_group_arr = $this->auth->group_arr;
        $is_allow_all = count(array_intersect(['1', '2', '3', '10'],$auth_group_arr));
        $admin_id = $this->auth->id;
        $res = $this->model
            ->withJoin($this->withJoinTable, $this->withJoinType)
            ->alias($alias)
            ->where($where)
            ->whereRaw($is_allow_all.' > 0 or manager_id = "'.$admin_id.'" or creater_id = "'.$admin_id.'" or find_in_set("'.$admin_id.'", member_ids)')
            ->order($order)
            ->paginate($limit);
        $res->visible(['manager' => ['nickname']]);

        $this->success('', [
            'list'   => $res->items(),
            'total'  => $res->total(),
            'remark' => get_route_remark(),
        ]);
    }

    /**
     * 添加
     */
    public function add(): void
    {
        if ($this->request->isPost()) {
            $data = $this->request->post();
            if (!$data) {
                $this->error(__('Parameter %s can not be empty', ['']));
            }

            $data = $this->excludeFields($data);
            if ($this->dataLimit && $this->dataLimitFieldAutoFill) {
                $data[$this->dataLimitField] = $this->auth->id;
            }

            $result = false;
            $this->model->startTrans();
            try {
                // 模型验证
                if ($this->modelValidate) {
                    $validate = str_replace("\\model\\", "\\validate\\", get_class($this->model));
                    if (class_exists($validate)) {
                        $validate = new $validate;
                        if ($this->modelSceneValidate) $validate->scene('add');
                        $validate->check($data);
                    }
                }
                $data['creater_id'] = $this->auth->id;
                $result = $this->model->save($data);
                $this->model->commit();
            } catch (Throwable $e) {
                $this->model->rollback();
                $this->error($e->getMessage());
            }
            if ($result !== false) {
                $this->success(__('Added successfully'));
            } else {
                $this->error(__('No rows were added'));
            }
        }

        $this->error(__('Parameter error'));
    }
    /**
     * 若需重写查看、编辑、删除等方法，请复制 @see \app\admin\library\traits\Backend 中对应的方法至此进行重写
     */

    public function statics(): void
    {
        $project_id = request()->post('project_id');
        $detail = $this->model->withJoin($this->withJoinTable, $this->withJoinType)->find($project_id);
        $ProjectFeeitemModel = new \app\admin\model\ProjectFeeitem();
        // 项目各分类占比多少
        $statics = $ProjectFeeitemModel
            ->field('feeitem_pid id, feeitem_pname title, sum(budget) budget, sum(calculate) calculate, sum(paid) paid, sum(calculate - paid) no_paid')
            ->where([
                ['project_id', '=', $project_id]
            ])->group('feeitem_pid, feeitem_pname')->select()->toArray();
        // 项目付款支出
        $advance = Advance::where([
            ['project_id', '=', $project_id],
            ['audit_state', '=', 2]
        ])->sum('amount');
        // 项目预支支出
        $payment = Payment::where([
            ['project_id', '=', $project_id],
            ['audit_state', '=', 2]
        ])->sum('pay_amount');
        // 项目报销支出
        $reimbursement = Reimbursement::where([
            ['project_id', '=', $project_id],
            ['audit_state', '=', 2]
        ])->sum('amount');

        // 各费用项-预支总额
        $advance_list = Advance::where([
            ['project_id', '=', $project_id],
            ['audit_state', 'in', [1,3]]
        ])->select()->toArray();

        $advance_statics = [];
        foreach ($advance_list as $v) {
            try {
                $feeitems = json_decode($v['feeitems'], true);
            } catch (Exception) {
                $feeitems = [];
            }
            foreach ($feeitems as $feeitem){
                if(isset($advance_statics[$feeitem['feeitem_id']])){
                    $advance_statics[$feeitem['feeitem_id']]['amount'] =  bcadd($advance_statics[$feeitem['feeitem_id']]['amount'], $feeitem['amount']);
                }  else {
                    $advance_statics[$feeitem['feeitem_id']] = $feeitem;
                }
            }
        }

        $this->success('', [
            'detail'   => $detail,
            'statics'  => $statics,
            'advance' => $advance,
            'payment' => $payment,
            'advance_statics' => $advance_statics,
            'reimbursement' => $reimbursement
        ]);
    }

    public function wfrecord(): void
    {
        $project_id = request()->post('project_id');
        $advance = Advance::where([
            ['project_id', '=', $project_id],
        ])->with(['project', 'feeitem'])->select();
        $payment = Payment::where([
            ['project_id', '=', $project_id],
        ])->with(['project', 'supplier', 'feeitem'])->select();
        $reimbursement = Reimbursement::where([
            ['project_id', '=', $project_id],
        ])->with(['project',  'feeitem'])->select();

        $this->success('', [
            'advance' => $advance,
            'payment' => $payment,
            'reimbursement' => $reimbursement
        ]);
    }

    public function export(){
//        $project_id = request()->post('project_id');
//        $Utils = new Utils();
//        $export_data = [];
//        $keys = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N'];
//        $db_datas = \app\admin\model\ProjectFeeitem::where([
//            ['project_id', '=', $project_id]
//        ])->select()->toArray();
//        $hasTopKey = [];
//        foreach ($db_datas as $v){
//            if(!isset($hasTopKey[$v['feeitem_pid']])) {
//                $export_data[] = [$keys[count($hasTopKey)].'.', $v['feeitem_name'], 'UNIT', 'QTY', 'TERMS', 'RATE', '预算栏', '核算栏', '备注栏'];
//                $hasTopKey[$v['feeitem_pid']] = 1;
//            }
//            $export_data[] = [$v['feeitem_name'], '', $v['unit'], $v['qty'], $v['trems'], $v['rate'],$v['budget'],$v['calculate'],  ''];
//        }
//        $filename = date('YmdHis').'_'.random_int(10,99);
//        $filePath = $Utils->putCsv($filename, $export_data);
//        $this->success('', [
//            "file"=> $filePath
//        ]);
        $detail = $this->request->post('detail');
        $statics = $this->request->post('statics');
        $tableData = $this->request->post('tableData');
        $projectTotal = $this->request->post('projectTotal');
        $advance_statics = $this->request->post('advance_statics');

        $spreadsheet = new Spreadsheet();
        $activeWorksheet = $spreadsheet->getActiveSheet();
        $activeWorksheet->setCellValue('A1', 'Hello World !');
        $cellKey = ['A','B','C','D','E','F','G','H','I','J','K','L','M', 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];
        $activeWorksheet->getStyle('A:L')->getAlignment()->setHorizontal('center');
        $activeWorksheet->getStyle('A:L')->getAlignment()->setVertical('center');
        $activeWorksheet->getDefaultRowDimension()->setRowHeight(30);
        $activeWorksheet->getColumnDimension('A')->setWidth(13);
        $activeWorksheet->getColumnDimension('B')->setWidth(26);
        $activeWorksheet->getColumnDimension('C')->setWidth(17);
        $activeWorksheet->getColumnDimension('D')->setWidth(17);
        $activeWorksheet->getColumnDimension('E')->setWidth(17);
        $activeWorksheet->getColumnDimension('F')->setWidth(17);
        $activeWorksheet->getColumnDimension('G')->setWidth(17);
        $activeWorksheet->getColumnDimension('H')->setWidth(17);
        $activeWorksheet->getColumnDimension('I')->setWidth(17);
        $activeWorksheet->getColumnDimension('J')->setWidth(17);
        $activeWorksheet->getColumnDimension('K')->setWidth(17);
        $activeWorksheet->getColumnDimension('L')->setWidth(60);
        $activeWorksheet->setCellValue('A1', 'PRODUCTION ESTIMATE');
        $activeWorksheet->mergeCells('A1:C1');
        $activeWorksheet->setCellValue('D1', $detail['custom_company']);
        $activeWorksheet->mergeCells('D1:K1');
        $activeWorksheet->setCellValue('L1', '');

        $activeWorksheet->setCellValue('A2', 'Client  客户：');
        $activeWorksheet->mergeCells('A2:B2');
        $activeWorksheet->setCellValue('C2', $detail['custom_name']);
        $activeWorksheet->setCellValue('D2', '片名：');
        $activeWorksheet->mergeCells('D2:G2');
        $activeWorksheet->setCellValue('H2', $detail['title']);
        $activeWorksheet->mergeCells('H2:K2');

        $activeWorksheet->setCellValue('A3', 'Creative Director 创意总监：');
        $activeWorksheet->mergeCells('A3:B3');
        $activeWorksheet->setCellValue('C3', $detail['creative_director']);
        $activeWorksheet->setCellValue('D3', 'Language  语言:');
        $activeWorksheet->mergeCells('D3:G3');
        $activeWorksheet->setCellValue('H3', $detail['language']);
        $activeWorksheet->mergeCells('H3:K3');

        $activeWorksheet->setCellValue('A4', 'Director  导演：');
        $activeWorksheet->mergeCells('A4:B4');
        $activeWorksheet->setCellValue('C4', $detail['director']);
        $activeWorksheet->setCellValue('D4', 'Prep Days  前期:');
        $activeWorksheet->mergeCells('D4:G4');
        $activeWorksheet->setCellValue('H4', '');
        $activeWorksheet->mergeCells('H4:K4');

        $activeWorksheet->setCellValue('A5', 'DOP  摄影：');
        $activeWorksheet->mergeCells('A5:B5');
        $activeWorksheet->setCellValue('C5', '');
        $activeWorksheet->setCellValue('D5', 'Post Days  前期:');
        $activeWorksheet->mergeCells('D5:G5');
        $activeWorksheet->setCellValue('H5', '');
        $activeWorksheet->mergeCells('H5:K5');

        $activeWorksheet->setCellValue('A6', 'Production Company 制作公司：');
        $activeWorksheet->mergeCells('A6:B6');
        $activeWorksheet->setCellValue('C6', '');
        $activeWorksheet->setCellValue('D6', 'Studio Shooting Day  棚内天数:');
        $activeWorksheet->mergeCells('D6:G6');
        $activeWorksheet->setCellValue('H6', '');
        $activeWorksheet->mergeCells('H6:K6');

        $activeWorksheet->setCellValue('A7', 'Executive Producer  监制：');
        $activeWorksheet->mergeCells('A7:B7');
        $activeWorksheet->setCellValue('C7', '');
        $activeWorksheet->setCellValue('D7', '长度:');
        $activeWorksheet->mergeCells('D7:G7');
        $activeWorksheet->setCellValue('H7', '');
        $activeWorksheet->mergeCells('H7:K7');

        $activeWorksheet->setCellValue('A8', 'Producer  制片：');
        $activeWorksheet->mergeCells('A8:B8');
        $activeWorksheet->setCellValue('C8', '');
        $activeWorksheet->setCellValue('D8', 'Date  制表日期:');
        $activeWorksheet->mergeCells('D8:G8');
        $activeWorksheet->setCellValue('H8', $detail['date']);
        $activeWorksheet->mergeCells('H8:K8');

        $activeWorksheet->mergeCells('A9:K9');

        $activeWorksheet->setCellValue('A10', 'Estimated Production Cost  制作成本');
        $activeWorksheet->mergeCells('A10:G10');
        $activeWorksheet->setCellValue('H10', '预算栏');
        $activeWorksheet->setCellValue('I10', '核算栏');
        $activeWorksheet->setCellValue('J10', '已支付');
        $activeWorksheet->setCellValue('K10', '未支付');

        $rowIndex = 11;
        foreach ($statics as $i => $v){
            $activeWorksheet->setCellValue('A'.$rowIndex, $cellKey[$i] ?? '');
            $activeWorksheet->setCellValue('B'.$rowIndex, $v['title']);
            $activeWorksheet->mergeCells('B'.$rowIndex.':G'.$rowIndex);
            $activeWorksheet->setCellValue('H'.$rowIndex, $v['budget']);
            $activeWorksheet->setCellValue('I'.$rowIndex, $v['calculate']);
            $activeWorksheet->setCellValue('J'.$rowIndex, $v['paid']);
            $activeWorksheet->setCellValue('K'.$rowIndex, $v['no_paid']);
            $rowIndex++;
        }
        $activeWorksheet->mergeCells('A'.$rowIndex.':K'.$rowIndex);
        $rowIndex++;
        $activeWorksheet->setCellValue('A'.$rowIndex, 'Total 总签价');
        $activeWorksheet->mergeCells('A'.$rowIndex.':K'.$rowIndex);
        $rowIndex++;
        $activeWorksheet->setCellValue('A'.$rowIndex, 'Sub Total');
        $activeWorksheet->mergeCells('A'.$rowIndex.':B'.$rowIndex);
        $activeWorksheet->setCellValue('C'.$rowIndex, '总价无税金');
        $activeWorksheet->mergeCells('C'.$rowIndex.':G'.$rowIndex);
        $activeWorksheet->setCellValue('H'.$rowIndex, $projectTotal['total']['budget']);
        $activeWorksheet->setCellValue('I'.$rowIndex, $projectTotal['total']['calculate']);
        $rowIndex++;
        $activeWorksheet->setCellValue('A'.$rowIndex, '税金Tax (总签价*)');
        $activeWorksheet->mergeCells('A'.$rowIndex.':B'.$rowIndex);
        $activeWorksheet->setCellValue('C'.$rowIndex, $detail['tax'].'%增值税抵扣发票');
        $activeWorksheet->mergeCells('C'.$rowIndex.':G'.$rowIndex);
        $activeWorksheet->setCellValue('H'.$rowIndex, $projectTotal['total']['budget_rate']);
        $activeWorksheet->setCellValue('I'.$rowIndex, $projectTotal['total']['calculate_rate']);
        $rowIndex++;
        $activeWorksheet->setCellValue('A'.$rowIndex, 'TOTAL (RMB)');
        $activeWorksheet->mergeCells('A'.$rowIndex.':B'.$rowIndex);
        $activeWorksheet->setCellValue('C'.$rowIndex, '总支出（人民币含税）');
        $activeWorksheet->mergeCells('C'.$rowIndex.':G'.$rowIndex);
        $activeWorksheet->setCellValue('H'.$rowIndex, $projectTotal['total']['budget_total']);
        $activeWorksheet->setCellValue('I'.$rowIndex, $projectTotal['total']['calculate_total']);
        $activeWorksheet->setCellValue('J'.$rowIndex, $projectTotal['total']['paid']);
        $activeWorksheet->setCellValue('K'.$rowIndex, $projectTotal['total']['no_paid']);
        $rowIndex++;
        $activeWorksheet->mergeCells('A'.$rowIndex.':K'.$rowIndex);
        $rowIndex++;
        foreach ($tableData as $i => $v){
            $activeWorksheet->setCellValue('A'.$rowIndex, $v['title']);
            $activeWorksheet->mergeCells('A'.$rowIndex.':B'.$rowIndex);
            $activeWorksheet->setCellValue('C'.$rowIndex, "备注");
            $activeWorksheet->setCellValue('D'.$rowIndex, 'UNIT');
            $activeWorksheet->setCellValue('E'.$rowIndex, 'QTY');
            $activeWorksheet->setCellValue('F'.$rowIndex, 'TERMS');
            $activeWorksheet->setCellValue('G'.$rowIndex, 'RATE');
            $activeWorksheet->setCellValue('H'.$rowIndex, '预算栏');
            $activeWorksheet->setCellValue('I'.$rowIndex, '核算栏');
            $activeWorksheet->setCellValue('J'.$rowIndex, '已支付');
            $activeWorksheet->setCellValue('K'.$rowIndex, '未支付');
            $activeWorksheet->setCellValue('L'.$rowIndex, '预支');
            $rowIndex++;
            foreach ($v['children'] as $ii => $item){
                $activeWorksheet->setCellValue('A'.$rowIndex, $ii+1);
                $activeWorksheet->setCellValue('B'.$rowIndex, $item['title']);
                $activeWorksheet->setCellValue('C'.$rowIndex, $item['remark']);
                $activeWorksheet->setCellValue('D'.$rowIndex, $item['unit']);
                $activeWorksheet->setCellValue('E'.$rowIndex, $item['qty']);
                $activeWorksheet->setCellValue('F'.$rowIndex, $item['trems']);
                $activeWorksheet->setCellValue('G'.$rowIndex, $item['rate']);
                $activeWorksheet->setCellValue('H'.$rowIndex, $item['budget']);
                $activeWorksheet->setCellValue('I'.$rowIndex, $item['calculate']);
                $activeWorksheet->setCellValue('J'.$rowIndex, $item['paid'] ?? "");
                $activeWorksheet->setCellValue('K'.$rowIndex, $item['no_paid'] ?? "");
                $activeWorksheet->setCellValue('L'.$rowIndex, !empty($advance_statics[$item['id']]) ? $advance_statics[$item['id']]['amount'] : "");
                $rowIndex++;
            }
            $activeWorksheet->setCellValue('A'.$rowIndex, 'Sub Total');
            $activeWorksheet->setCellValue('C'.$rowIndex, '共计');
            $activeWorksheet->setCellValue('H'.$rowIndex, $statics[$i]['budget']);
            $activeWorksheet->setCellValue('I'.$rowIndex, $statics[$i]['calculate']);
            $activeWorksheet->setCellValue('J'.$rowIndex, $statics[$i]['paid']);
            $activeWorksheet->setCellValue('K'.$rowIndex, $statics[$i]['no_paid']);
            $rowIndex++;
            $activeWorksheet->mergeCells('A'.$rowIndex.':K'.$rowIndex);
            $rowIndex++;
        }
        for($i = 1; $i <= $rowIndex; $i++)
        {
            $activeWorksheet->getRowDimension($i)->setRowHeight(30);
        }

        $writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, "Xlsx");
        $filename = $detail['title'].'-'.date('YmdHis').'.xlsx';
//        header('pragma:public');
//        header('Content-type:application/vnd.ms-excel;charset=utf-8;name="'.$filename);
//        header("Content-Disposition:attachment;filename=".$filename);
//        $writer->save('php://output');
        $writer->save('export/'.$filename);
        $this->success('',['file' => '/export/'.$filename]);
    }

    public function toAudit(){
        $data = $this->request->post();
        try {
            // 检查是否有未完成的 预算审批
            // 未完成的预算审批 直接撤销
            $project_model = \app\common\model\Project::find($data['project_id']);

            $wf = \app\common\model\workflow\Workflow::where([
                ['extend', '=', $project_model->id],
                ['state', 'in', ['0','1']]
            ])->findOrEmpty();
            $admin = $this->auth->getAdmin()->toArray();
            if(!$wf->isEmpty()){
                $Workflow = new Workflow($wf['flow_no'], $admin);
                $Workflow->cancel(['id' => $this->auth->id, 'nickname' => $this->auth->nickname]);
            }
            $WFCreate = new WFCreate($admin);
            $project_data = json_decode(json_encode($project_model), true);
            $project_data['project_id'] = $project_data['id'];

            $WF = $WFCreate->create_flow(400, $project_data, $project_model->title.' 预算申请 ', $project_model->id);
            $Workflow = new Workflow($WF['flow_no'], $admin);
            $Workflow->start();

            $project_model->budget_audit_state = 1;
            $project_model->save();
            $this->success('操作成功');
        } catch (Exception $e) {
            $this->error('操作失败', [
                "msg" => $e->getMessage(),
                "file" => $e->getFile(),
                "line" => $e->getLine()
            ]);
        }
    }
}